package org.dubnation.org.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.dubnation.base.constants.SystemConstants;
import org.dubnation.base.enums.ResponseCode;
import org.dubnation.base.exception.BusinessException;
import org.dubnation.base.exception.SensitiveInfoException;
import org.dubnation.base.util.audit.ActiveCode;
import org.dubnation.base.util.address.DistanceUtil;
import org.dubnation.base.util.address.Point;
import org.dubnation.base.util.audit.BaiduAuditUtils;
import org.dubnation.base.util.audit.DubnationAssert;
import org.dubnation.base.util.encryption.MD5Utils;
import org.dubnation.org.domain.Employee;
import org.dubnation.org.domain.Shop;
import org.dubnation.org.domain.ShopEmployee;
import org.dubnation.org.domain.ShopOperateLog;
import org.dubnation.org.mapper.EmployeeMapper;
import org.dubnation.org.mapper.ShopEmployeeMapper;
import org.dubnation.org.mapper.ShopMapper;
import org.dubnation.org.mapper.ShopOperateLogMapper;
import org.dubnation.org.service.IEmployeeService;
import org.dubnation.org.service.IShopService;
import org.dubnation.base.service.impl.BaseServiceImpl;
import org.dubnation.user.domain.LoginInfo;
import org.dubnation.user.mapper.LoginInfoMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zhu
 * @since 2023-10-27
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class ShopServiceImpl extends BaseServiceImpl<Shop> implements IShopService {

    @Autowired(required = false)
    private ShopMapper shopMapper;

    @Autowired(required = false)
    private EmployeeMapper employeeMapper;

    @Autowired(required = false)
    private ShopEmployeeMapper shopEmployeeMapper;

    @Autowired
    private ShopEmployee shopEmployee;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    @Autowired
    private IEmployeeService employeeService;

    @Autowired
    private ActiveCode activeCode;

    @Autowired
    private ShopOperateLog shopOperateLog;

    @Autowired(required = false)
    private ShopOperateLogMapper shopOperateLogMapper;

    @Autowired(required = false)
    private LoginInfoMapper loginInfoMapper;

    @Autowired
    private LoginInfo loginInfo;

    /**
     * 商店入驻
     *    1.数据校验[非空校验、密码校验、店铺名称是否重复校验]
     *    2.数据格式验证
     *    3.数据审核[文本审核、图片审核] --审核次数大于3次时转为人工审核
     *      3.1 审核通过：修改店铺状态为待激活，发送激活邮件，店铺激活之后修改状态为已激活
     *      3.2 审核未通过：修改店铺状态为驳回，发送驳回邮件重新修改店铺入驻信息
     *    4.数据入库[店铺信息入库、员工信息入库、店铺与员工关联信息]，审核未通过不应入库
     *    5.记录店铺入驻日志
     * @param shop
     */
    @Transactional
    @Override
    public void settleIn(Shop shop) {
        //1.数据校验 (非空校验、格式校验，判断该店铺是否已存在)
        Employee admin = shop.getAdmin();
        DubnationAssert.isEq(admin.getPassword(), admin.getConfirmPassword(), ResponseCode.RESPONSE_CODE_400001);
        Shop shopOfDataBase = shopMapper.queryByName(shop.getName());
        DubnationAssert.isNull(shopOfDataBase, ResponseCode.RESPONSE_CODE_400002);
        //2.数据审核 (店铺名、店铺地址、店铺logo审核)
        List<String> censorText = Arrays.asList(shop.getName(), shop.getAddress());
        List<Map<String, Object>> censorResList = BaiduAuditUtils.censor(censorText, Arrays.asList(shop.getLogo()));
        StringBuffer errMsg = new StringBuffer();
        censorResList.forEach(censorRes -> {
            if (!Boolean.valueOf(censorRes.get("success").toString())){
                if (errMsg.equals("")){
                    errMsg.append(censorRes.get("message").toString());
                }else {
                    errMsg.append("," + censorRes.get("message").toString());
                }
            }
        });
        if (!errMsg.equals("")){
            throw new BusinessException(errMsg.toString());
        }
        //3.店铺数据入库
        //设置变量值
        shop.setRegisterTime(new Date());
        shop.setState(SystemConstants.Shop.AUDIT);
        Point point = DistanceUtil.getPoint(shop.getAddress());
        shop.setLng(point.getLng());
        shop.setLat(point.getLat());
        shop.setRejectedNum(0);
        shopMapper.insert(shop);
        //4.判断入驻管理员是否已存在, 若已存在则进行店铺关联即可
        Employee employee = employeeMapper.queryByUsername(admin.getUsername());
        if (Objects.isNull(employee)){
            //该入驻员工不存在
            admin.setAge(35);
            admin.setSex(1);
            String salt = UUID.randomUUID().toString();
            String password = MD5Utils.encryptionByMd5("kisc1130" + salt + admin.getPassword());
            admin.setSalt(salt);
            admin.setPassword(password);
            admin.setState(SystemConstants.Employee.UNAVAILABLE);
            //注册该员工信息并新增员工数据
            BeanUtils.copyProperties(admin, loginInfo);
            loginInfo.setType(LoginInfo.TYPE_ADMINISTRATORS);
            loginInfo.setDisable(LoginInfo.DISABLE_UNAVAILABLE); //激活后可用
            loginInfoMapper.insert(loginInfo);
            admin.setLoginInfoId(loginInfo.getId());
            employeeMapper.insert(admin);
            shopEmployee.setEmployeeId(admin.getId());
            activeCode.setEmployeeId(admin.getId());
            shopOperateLog.setOperateId(admin.getId());
            activeCode.setEmployeeId(admin.getId());
        }else {
            //入驻员工存在
            shopEmployee.setEmployeeId(employee.getId());
            activeCode.setEmployeeId(employee.getId());
        }
        //5.店铺和管理员数据关联
        shopEmployee.setShopId(shop.getId());
        shopEmployee.setIsAdmin(SystemConstants.ShopEmployee.IS_ADMIN);
        shopEmployeeMapper.insert(shopEmployee);
        //6.审核通过发送激活邮件
        activeCode.setShopId(shop.getId());
        redisTemplate.opsForValue().set(SystemConstants.Employee.ACTIVE_CODE, activeCode);
        try {
            employeeService.shopAuditPass(shop);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        //7.记录店铺入驻日志
        shopOperateLog.setShopId(shop.getId());
        shopOperateLog.setOperateTime(new Date());
        shopOperateLog.setOperateType(SystemConstants.ShopOperateLog.SETTLE_IN);
        shopOperateLog.setNote("店铺入驻");
        shopOperateLogMapper.insert(shopOperateLog);
    }

    /**
     *审核商店信息是否合法 (全部审核完成之后错误统一返回前端)
     * @param shop
     * @return
     */
    @Override
    public void audit(Shop shop) {
        StringBuffer errMsg = new StringBuffer();
        //1.审核商店名、店铺地址和商店logo是否包含违禁信息
        List<String> auditInfo = Arrays.asList(shop.getAddress(), shop.getName());
        List<Map<String, Object>> censorResList = BaiduAuditUtils.censor(auditInfo, Arrays.asList(shop.getLogo()));
        censorResList.forEach(censorRes -> {
            if (!Boolean.valueOf(censorRes.get("success").toString())){
                if (errMsg.equals("")){
                    errMsg.append(censorRes.get("message").toString());
                }else {
                    errMsg.append("," + censorRes.get("message").toString());
                }
            }
        });
        //3.审核商店地址是否存在
        Point point = DistanceUtil.getPoint(shop.getAddress());
        Double lng = point.getLng();
        Double lat = point.getLat();
        if (!(lng > 0 && lng <180 && lat > 0 && lat < 90)){
            //地址不存在
            errMsg.append("," + ResponseCode.RESPONSE_CODE_400004.getMessage());
        }
        //4.审核管理员手机号码是否合规
        String phoneRegex = "^1[3-9]\\d{9}$";
        Pattern phonePattern = Pattern.compile(phoneRegex);
        Matcher matcher = phonePattern.matcher(shop.getAdmin().getPhone());
        if (!matcher.matches()){
            //手机号码不合法
            errMsg.append("," + ResponseCode.RESPONSE_CODE_400005.getMessage());
        }
        if (!(errMsg.equals(null) || errMsg.equals(""))){
            //有错误信息就返回
            throw new BusinessException(errMsg.toString());
        }
    }

    @Override
    public Shop queryByLogo(String path) {
        return shopMapper.queryByLogo(path);
    }

    /**
     * 激活账户
     * @param code
     */
    @Transactional
    @Override
    public void activeAccount(String code) {
        //获取激活码
        ActiveCode activeCode = (ActiveCode) redisTemplate.opsForValue().get(code);
        if (activeCode == null) throw new BusinessException(ResponseCode.RESPONSE_CODE_400008);
        //修改店铺状态--激活成功
        Shop shop = shopMapper.queryById(activeCode.getShopId());
        shop.setState(Shop.ACTIVATED);
        shopMapper.update(shop);
        //修改管理员状态--账户可用
        Employee employee = employeeMapper.queryById(activeCode.getEmployeeId());
        employee.setState(Employee.AVAILABLE);
        employeeMapper.update(employee);
    }

    /**
     * 修改店铺状态--待激活
     * @param shop
     */
    @Transactional
    @Override
    public void update(Shop shop) {
        shop.setState(Shop.TO_BE_ACTIVATED);
        shopMapper.update(shop);
    }

    /**
     * 获取店铺管理员
     * @return
     */
    @Override
    public List<Employee> getAdmins() {
        return shopMapper.getAdmins();
    }
}
